﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ObjectSearch.Configuration
{
    public class ObjectMetaData
    {
        /// <summary>
        /// A private field used to hold the value for Fields property.
        /// </summary>
        private List<FieldMetaData> _Fields;

        public List<FieldMetaData> Fields
        {
            get
            {
                return _Fields;
            }
        }

        /// <summary>
        /// A private field used to hold the value for ObjectType property.
        /// </summary>
        private Type _ObjectType;

        public Type ObjectType
        {
            get
            {
                return _ObjectType;
            }
            set
            {
                _ObjectType = value;
            }
        }

        public ObjectMetaData()
        {
            _Fields = new List<FieldMetaData>();
        }

        public FieldMetaData FindByLuceneFieldName(string fieldName)
        {
            foreach (var item in this.Fields)
            {
                if (item.FieldName.Equals(fieldName))
                {
                    return item;
                }
            }

            return null;
        }

        public FieldMetaData FindByObjectMemberName(string memberName)
        {
            foreach (var item in this.Fields)
            {
                if (item.MemberName.Equals(memberName))
                {
                    return item;
                }
            }

            return null;
        }

        public FieldMetaData FindKeyField()
        {
            foreach (var item in this.Fields)
            {
                if (item.IsUniqueKey)
                    return item;
            }

            return null;
        }

        public void Validate()
        {
            if (ObjectType == null)
                throw new LuceneException("The ObjectType value cannot be null.");

            if (Fields.Count == 0)
                throw new LuceneException(string.Format("ObjectMetaData error for type of {0}, has no registered fields to index.", ObjectType.FullName));

            List<string> fieldNames = new List<string>();
            string DefaultSearchFieldName = null;
            string KeyFieldName = null;

            foreach (FieldMetaData f in this.Fields)
            {
                if (f.FieldName == null || f.FieldName.Trim() == string.Empty)
                    throw new LuceneException(string.Format("ObjectMetaData error for type of {0}, has a registered field without a FieldName set.", ObjectType.FullName));
                if (f.MemberName == null || f.MemberName.Trim() == string.Empty)
                    throw new LuceneException(string.Format("ObjectMetaData error for type of {0}, has a registered field ({1}) without a MemberName set.", ObjectType.FullName, f.FieldName));

                if (DefaultSearchFieldName != null && f.IsDefaultSearchField)
                    throw new LuceneException(string.Format("ObjectMetaData error for type of {0}, has two registered fields that are set as the DefaultSearchField. Fields ({1} {2})", ObjectType.FullName, DefaultSearchFieldName, f.FieldName));

                if (f.IsDefaultSearchField)
                    DefaultSearchFieldName = f.FieldName;


                if (KeyFieldName != null && f.IsUniqueKey)
                    throw new LuceneException(string.Format("ObjectMetaData error for type of {0}, has two registered fields that are set as the Unique Key Field. Fields ({1} {2})", ObjectType.FullName, KeyFieldName, f.FieldName));

                if (f.IsUniqueKey)
                    KeyFieldName = f.FieldName;

                if (fieldNames.Contains(f.FieldName))
                    throw new LuceneException(string.Format("ObjectMetaData error for type of {0}, has two registered fields with the same FieldName of {1}", ObjectType.FullName, f.FieldName));

                fieldNames.Add(f.FieldName);
            }

            if (DefaultSearchFieldName == null)
                throw new LuceneException(string.Format("ObjectMetaData error for type of {0}, is missing a Default Search Field.", ObjectType.FullName));
            if (KeyFieldName == null)
                throw new LuceneException(string.Format("ObjectMetaData error for type of {0}, is missing a Unique Key Field.", ObjectType.FullName));
        }

        public override string ToString()
        {
            return "ObjectMetaDate: " + this.ObjectType.Name;
        }
    }
}
